#include <iostream>

using namespace std;

enum Product_Type {
    PRODUCT_TYPE_A,

    PRODUCT_TYPE_B,
};

class Product {
public:
    virtual void doSomeThing() = 0;
};

class Factory {
public:
    virtual Product *createProduct() = 0;
};

class ProductA : public Product {
public:
    void doSomeThing() override {
        cout << "Product A Do Some Thing!" << endl;
    }
};

class ProductB : public Product {
public :
    void doSomeThing() override {
        cout << "Product B Do Some Thing!" << endl;
    }
};

class SimpleFactory {
public:
    Product *createProduct(Product_Type type) {
        Product *instance = nullptr;

        switch (type) {
            case PRODUCT_TYPE_A:
                instance = new ProductA();
                break;
            case PRODUCT_TYPE_B:
                instance = new ProductB();
                break;
        }

        return instance;
    }
};

class FactoryA : public Factory {
public:
    Product *createProduct() override {
        Product *instance = nullptr;
        instance = new ProductA();
        return instance;
    }
};

class FactoryB : public Factory {
public:
    Product *createProduct() override {
        Product *instance = nullptr;
        instance = new ProductB();
        return instance;
    }
};

void test01() {
    Product *product = nullptr;
    SimpleFactory *factory = nullptr;

    factory = new SimpleFactory();

    product = factory->createProduct(PRODUCT_TYPE_A);
    product->doSomeThing();
    delete product;

    product = factory->createProduct(PRODUCT_TYPE_B);
    product->doSomeThing();
    delete product, factory;

    cout << endl;
}

void test02() {
    Product *product = nullptr;
    Factory *factory = nullptr;

    factory = new FactoryA();
    product = factory->createProduct();
    product->doSomeThing();
    delete product, factory;

    factory = new FactoryB();
    product = factory->createProduct();
    product->doSomeThing();
    delete product, factory;

    cout << endl;
}

int main() {
    test01();

    test02();
}